﻿//---------------------------------------------------------------------
// Copyright (c) 2007 Digerati Technologies, LLC.  All Rights Reserved.
//
// Release under the Microsoft Public License (Ms-PL).
//---------------------------------------------------------------------

using System;
using System.Diagnostics;
using System.IO;

namespace DigeratiTech.NDiagnostics
{
    /// <summary>
    /// This <see cref="DiagnosticTask"/> verifies that the specified file exists.
    /// </summary>
    public class ExecTask : DiagnosticTask
    {
        #region Properties...

        /// <summary>
        /// Gets or sets the path to the executable to be ran.
        /// </summary>
        /// <value>The path to the executable to be ran.</value>
        /// <remarks>The executable proram must return an exit code of zero (0) for this task to succeed.</remarks>
        public string Path { get; set; }

        /// <summary>
        /// Gets or sets the arguments to be passed into via the command line when starting the process.
        /// </summary>
        /// <value>The arguments to be passed into via the command line when starting the process.</value>
        public string Arguments { get; set; }

        /// <summary>
        /// Gets or sets the expected exit code.
        /// </summary>
        /// <value>The expected exit code.</value>
        public int ExitCode { get; set; }

        #endregion

        #region Constructors...

        /// <summary>
        /// Initializes a new instance of the <see cref="ExecTask"/> class.
        /// </summary>
        /// <param name="group">The <see cref="TaskGroup"/> this task belongs to.</param>
        /// <param name="name">The task name.</param>
        /// <param name="path">The path to the executable to run.</param>
        /// <param name="arguments">Any (optional) arguments to be passed into the process.</param>
        /// <param name="exitCode">The expected exit code.</param>
        public ExecTask(TaskGroup group, string name, string path, string arguments, int exitCode)
        {
            taskGroup = group;
            Name = name;
            Path = path;
            Arguments = arguments;
            ExitCode = exitCode;
            Status = TaskStatus.NotRun;
        }

        #endregion

        #region Methods...

        /// <summary>
        /// Executes the task.
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if the task is successful; otherwise, <c>false</c>.
        /// </returns>
        public override bool Execute()
        {
            ProcessStartInfo startInfo;
            Process theProcess = null;
            Status = TaskStatus.Completed;
            Message = string.Empty;

            try
            {
                // Configure the process to be ran
                if (string.IsNullOrEmpty(Arguments))
                {
                    startInfo = new ProcessStartInfo(Path);
                }
                else
                {
                    startInfo = new ProcessStartInfo(Path, Arguments);
                }

                startInfo.CreateNoWindow = true;
                startInfo.WindowStyle = ProcessWindowStyle.Hidden;

                // Run the process
                theProcess = Process.Start(startInfo);

                // Wait for the process to complete; timeout after 1 minute
                theProcess.WaitForExit(60000);

                if (!theProcess.HasExited)
                {
                    Status = TaskStatus.Error;
                    Message += ((Message.Length > 0) ? "\n" : "") + "This task has timed out waiting for the process to complete.";
                }
                else if (theProcess.ExitCode != ExitCode)
                {
                    Status = TaskStatus.Error;
                    Message += ((Message.Length > 0) ? "\n" : "") + string.Format("The process did not complete successfully.  The expected exit code is {0}; The actual exit code is {1}.", ExitCode, theProcess.ExitCode);
                }
            }
            catch (Exception ex)
            {
                Status = TaskStatus.Error;
                Message += ((Message.Length > 0) ? "\n" : "") + string.Format("The process could not be started: {0}.", ex.Message);
            }
            finally
            {
                if (theProcess != null)
                {
                    theProcess.Dispose();
                }
            }

            return (Message.Length == 0);
        }

        #endregion
    }
}
